home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / djgpp / contrib / dvx / demos / xeyes / eyes.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-15  |  12.7 KB  |  441 lines

  1. /*
  2.  * Eyes.c
  3.  *
  4.  * a widget which follows the mouse around
  5.  */
  6. #if defined(PROTO) || defined(PROTO1)
  7. #define NeedFunctionPrototypes    0
  8. #define NeedFunctionPtrPrototypes    1
  9. #endif
  10.  
  11. # include <X11/Xos.h>
  12. # include <stdio.h>
  13. # include <X11/IntrinsP.h> /* shortened IntrinsicP.h POHC 90/09/10 */
  14. # include <X11/StringDefs.h>
  15. # include <X11/Xmu/Converters.h>
  16. # include "EyesP.h"
  17. # include <math.h>
  18. #ifdef SHAPE
  19. # include <X11/extensio/shape.h> /* Shortened <X11/extensions/shape.h> POHC 91/03/13 */
  20. #endif
  21.  
  22. #if defined(PROTO) || defined(PROTO1)
  23. #include "eyes.fd1"
  24. #include "transform.fd1"
  25. #endif
  26.  
  27. #ifdef PROTO
  28. #include "eyes.fd2"
  29. #endif
  30.  
  31. #define offset(field) XtOffset(EyesWidget,eyes.field)
  32. #define goffset(field) XtOffset(Widget,core.field)
  33.  
  34. static XtResource resources[] = {
  35.     {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
  36.     goffset(width), XtRString, "150"},
  37.     {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
  38.     goffset(height), XtRString, "100"},
  39.     {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  40.         offset(puppixel), XtRString, "Black"},
  41.     {XtNoutline, XtCForeground, XtRPixel, sizeof(Pixel),
  42.         offset(outline), XtRString, "Black"},
  43.     {XtNcenterColor, XtCBackground, XtRPixel, sizeof (Pixel),
  44.         offset(center), XtRString, "White"},
  45.     {XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
  46.     offset (reverse_video), XtRString, "FALSE"},
  47.     {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int),
  48.         offset (backing_store), XtRString, "default"},
  49. #ifdef SHAPE
  50.     {XtNshapeWindow, XtCShapeWindow, XtRBoolean, sizeof (Boolean),
  51.     offset (shape_window), XtRString, "TRUE"},
  52. #endif
  53. };
  54.  
  55. #undef offset
  56. #undef goffset
  57.  
  58. # define NUM_EYES    2
  59. # define EYE_X(n)    ((n) * 2.0)
  60. # define EYE_Y(n)    (0.0)
  61. # define EYE_OFFSET    (0.1)    /* padding between eyes */
  62. # define EYE_THICK    (0.175)    /* thickness of eye rim */
  63. # define BALL_WIDTH    (0.3)
  64. # define BALL_PAD    (0.05)
  65. # define EYE_WIDTH    (2.0 - (EYE_THICK + EYE_OFFSET) * 2)
  66. # define EYE_HEIGHT    EYE_WIDTH
  67. # define BALL_HEIGHT    BALL_WIDTH
  68. # define BALL_DIST    ((EYE_WIDTH - BALL_WIDTH) / 2.0 - BALL_PAD)
  69. # define W_MIN_X    (-1.0 + EYE_OFFSET)
  70. # define W_MAX_X    (3.0 - EYE_OFFSET)
  71. # define W_MIN_Y    (-1.0 + EYE_OFFSET)
  72. # define W_MAX_Y    (1.0 - EYE_OFFSET)
  73.  
  74. # define TPointEqual(a, b)  ((a).x == (b).x && (a).y == (b).y)
  75. # define XPointEqual(a, b)  ((a).x == (b).x && (a).y == (b).y)
  76.  
  77. static long delays[] = { 50, 100, 200, 400, 0 }; /* Were int. POHC 91/05/09 */
  78.  
  79. static void Initialize(), Realize(), Destroy();
  80. static void Redisplay(), Resize ();
  81. static Boolean SetValues();
  82. static int repaint_window();
  83. static int draw_it ();
  84.  
  85. static void ClassInitialize();
  86.  
  87. EyesClassRec eyesClassRec = {
  88.     { /* core fields */
  89.     /* superclass        */    &widgetClassRec,
  90.     /* class_name        */    "Eyes",
  91.     /* size            */    sizeof(EyesRec),
  92.     /* class_initialize        */    ClassInitialize,
  93.     /* class_part_initialize    */    NULL,
  94.     /* class_inited        */    FALSE,
  95.     /* initialize        */    Initialize,
  96.     /* initialize_hook        */    NULL,
  97.     /* realize            */    Realize,
  98.     /* actions            */    NULL,
  99.     /* num_actions        */    0,
  100.     /* resources        */    resources,
  101.     /* num_resources        */    XtNumber(resources),
  102.     /* xrm_class        */    (XrmClass) NULL, /* POHC 92/06/01 */
  103.     /* compress_motion        */    TRUE,
  104.     /* compress_exposure    */    TRUE,
  105.     /* compress_enterleave    */    TRUE,
  106.     /* visible_interest        */    FALSE,
  107.     /* destroy            */    Destroy,
  108.     /* resize            */    Resize,
  109.     /* expose            */    Redisplay,
  110.     /* set_values        */    SetValues,
  111.     /* set_values_hook        */    NULL,
  112.     /* set_values_almost    */    NULL,
  113.     /* get_values_hook        */    NULL,
  114.     /* accept_focus        */    NULL,
  115.     /* version            */    XtVersion,
  116.     /* callback_private        */    NULL,
  117.     /* tm_table            */    NULL,
  118.     /* query_geometry        */    XtInheritQueryGeometry,
  119.     }
  120. };
  121.  
  122. static void ClassInitialize()
  123. {
  124.     XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
  125.             NULL, 0 );
  126. }
  127.  
  128. WidgetClass eyesWidgetClass = (WidgetClass) &eyesClassRec;
  129.  
  130. /* ARGSUSED */
  131. static void Initialize (greq, gnew)
  132.     Widget greq, gnew;
  133. {
  134.     EyesWidget w = (EyesWidget)gnew;
  135.     XtGCMask    valuemask;
  136.     XGCValues    myXGCV;
  137. #ifdef SHAPE
  138.     int shape_event_base, shape_error_base;
  139. #endif
  140.  
  141.     /*
  142.      * set the colors if reverse video; these are the colors used:
  143.      *
  144.      *     background - paper        white
  145.      *     foreground - text, ticks    black
  146.      *     border - border        black (foreground)
  147.      *
  148.      * This doesn't completely work since the parent has already made up a 
  149.      * border.  Sigh.
  150.      */
  151.     if (w->eyes.reverse_video) {
  152.     Pixel fg = w->eyes.puppixel;
  153.     Pixel bg = w->core.background_pixel;
  154.  
  155.     if (w->core.border_pixel == fg)
  156.          w->core.border_pixel = bg;
  157.     if (w->eyes.outline == fg)
  158.         w->eyes.outline = bg;
  159.     if (w->eyes.center == bg)
  160.         w->eyes.center = fg;
  161.     w->eyes.puppixel = bg;
  162.     w->core.background_pixel = fg;
  163.     }
  164.  
  165.     myXGCV.foreground = w->eyes.puppixel;
  166.     myXGCV.background = w->core.background_pixel;
  167.     valuemask = GCForeground | GCBackground;
  168.     w->eyes.pupGC = XtGetGC(gnew, valuemask, &myXGCV);
  169.  
  170.     myXGCV.foreground = w->eyes.outline;
  171.     valuemask = GCForeground | GCBackground;
  172.     w->eyes.outGC = XtGetGC(gnew, valuemask, &myXGCV);
  173.  
  174.     myXGCV.foreground = w->eyes.center;
  175.     myXGCV.background = w->eyes.puppixel;
  176.     valuemask = GCForeground | GCBackground;
  177.     w->eyes.centerGC = XtGetGC(gnew, valuemask, &myXGCV);
  178.  
  179.     w->eyes.update = 0;
  180.     /* wait for Realize to add the timeout */
  181.     w->eyes.interval_id = 0;
  182.  
  183.     w->eyes.pupil[0].x = w->eyes.pupil[1].x = -1000;
  184.     w->eyes.pupil[0].y = w->eyes.pupil[1].y = -1000;
  185.  
  186. #ifdef SHAPE
  187.     if (w->eyes.shape_window && !XShapeQueryExtension (XtDisplay (w),
  188.                                &shape_event_base,
  189.                                &shape_error_base))
  190.     w->eyes.shape_window = False;
  191.     w->eyes.shape_mask = 0;
  192.     w->eyes.shapeGC = 0;
  193. #endif
  194. }
  195.  
  196. static void Resize (gw)
  197.     Widget    gw;
  198. {
  199.     EyesWidget    w = (EyesWidget) gw;
  200.     XGCValues    xgcv;
  201.     Widget    parent;
  202.     int        x, y;
  203.  
  204.     if (XtIsRealized (gw))
  205.     {
  206.         XClearWindow (XtDisplay (w), XtWindow (w));
  207.         SetTransform (&w->eyes.t,
  208.                 0, w->core.width,
  209.                  w->core.height, 0,
  210.                 W_MIN_X, W_MAX_X,
  211.                 W_MIN_Y, W_MAX_Y);
  212. #ifdef SHAPE
  213.         if (w->eyes.shape_window) {
  214.             w->eyes.shape_mask = XCreatePixmap (XtDisplay (w), XtWindow (w),
  215.                 w->core.width, w->core.height, 1);
  216.             if (!w->eyes.shapeGC)
  217.                 w->eyes.shapeGC = XCreateGC (XtDisplay (w), w->eyes.shape_mask, 0L, &xgcv); /* L. POHC */
  218.             XSetForeground (XtDisplay (w), w->eyes.shapeGC, 0L); /* L. POHC */
  219.             XFillRectangle (XtDisplay (w), w->eyes.shape_mask, w->eyes.shapeGC, 0, 0,
  220.             w->core.width, w->core.height);
  221.             XSetForeground (XtDisplay (w), w->eyes.shapeGC, 1L); /* L. POHC */
  222.             eyeLiner (w, w->eyes.shape_mask, w->eyes.shapeGC, (GC) 0, 0);
  223.             eyeLiner (w, w->eyes.shape_mask, w->eyes.shapeGC, (GC) 0, 1);
  224.         x = y = 0;
  225.         for (parent = (Widget) w; XtParent (parent); parent = XtParent (parent)) {
  226.             x += parent->core.x + parent->core.border_width;
  227.             x += parent->core.y + parent->core.border_width;
  228.         }
  229.             XShapeCombineMask (XtDisplay (parent), XtWindow (parent), ShapeBounding,
  230.                           x, y, w->eyes.shape_mask, ShapeSet);
  231.             XFreePixmap (XtDisplay (w), w->eyes.shape_mask);
  232.         }
  233. #endif
  234.     }
  235. }
  236.  
  237. static void Realize (gw, valueMask, attrs)
  238.      Widget gw;
  239.      XtValueMask *valueMask;
  240.      XSetWindowAttributes *attrs;
  241. {
  242.     EyesWidget    w = (EyesWidget)gw;
  243.  
  244.     if (w->eyes.backing_store != Always + WhenMapped + NotUseful) {
  245.          attrs->backing_store = w->eyes.backing_store;
  246.     *valueMask |= CWBackingStore;
  247.     }
  248.     XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent,
  249.              *valueMask, attrs );
  250.     Resize (gw);
  251.     w->eyes.interval_id =
  252.         XtAddTimeOut(delays[w->eyes.update], draw_it, (caddr_t)gw);
  253. }
  254.  
  255. static void Destroy (gw)
  256.      Widget gw;
  257. {
  258.      EyesWidget w = (EyesWidget)gw;
  259.  
  260.      if (w->eyes.interval_id)
  261.     XtRemoveTimeOut (w->eyes.interval_id);
  262.      XtDestroyGC (w->eyes.pupGC);
  263.      XtDestroyGC (w->eyes.outGC);
  264.      XtDestroyGC (w->eyes.centerGC);
  265. }
  266.  
  267. /* ARGSUSED */
  268. static void Redisplay(gw, event, region)
  269.      Widget gw;
  270.      XEvent *event;
  271.      Region region;
  272. {
  273.     EyesWidget    w;
  274.  
  275.     w = (EyesWidget) gw;
  276.     w->eyes.pupil[0].x = -1000;
  277.     w->eyes.pupil[0].y = -1000;
  278.     w->eyes.pupil[1].x = -1000;
  279.     w->eyes.pupil[1].y = -1000;
  280.     (void) repaint_window ((EyesWidget)gw);
  281. }
  282.  
  283. static TPoint computePupil (num, mouse)
  284.     int        num;
  285.     TPoint    mouse;
  286. {
  287.     double    cx, cy;
  288.     double    dist;
  289.     double    angle;
  290.     double    x, y;
  291.     double    h;
  292.     double    a, b;
  293.     double    dx, dy;
  294.     TPoint    ret;
  295.  
  296.     dx = mouse.x - EYE_X(num);
  297.     dy = mouse.y - EYE_Y(num);
  298.     if (dx == 0 && dy == 0) {
  299.         cx = EYE_X(num);
  300.         cy = EYE_Y(num);
  301.     } else {
  302.         angle = atan2 ((double) dy, (double) dx);
  303.         a = EYE_WIDTH / 2.0;
  304.         b = EYE_HEIGHT / 2.0;
  305.         h = hypot (b * cos (angle), a * sin (angle));
  306.         x = a * b * cos (angle) / h;
  307.         y = a * b * sin (angle) / h;
  308.         dist = BALL_DIST * hypot (x, y);
  309.         if (dist > hypot ((double) dx, (double) dy)) {
  310.             cx = dx + EYE_X(num);
  311.             cy = dy + EYE_Y(num);
  312.         } else {
  313.             cx = dist * cos (angle) + EYE_X(num);
  314.             cy = dist * sin (angle) + EYE_Y(num);
  315.         }
  316.     }
  317.     ret.x = cx;
  318.     ret.y = cy;
  319.     return ret;
  320. }
  321.  
  322. static void computePupils (mouse, pupils)
  323.     TPoint    mouse;
  324.     TPoint    pupils[2];
  325. {
  326.     pupils[0] = computePupil (0, mouse);
  327.     pupils[1] = computePupil (1, mouse);
  328. }
  329.  
  330. /* ARGSUSED */
  331. static int draw_it(client_data, id)
  332.      caddr_t client_data;
  333.      XtIntervalId id;        /* unused */
  334. {
  335.         EyesWidget    w = (EyesWidget)client_data;
  336.     Window        rep_root, rep_child;
  337.     int        rep_rootx, rep_rooty;
  338.     unsigned int    rep_mask;
  339.     int        dx, dy;
  340.     TPoint        mouse;
  341.     Display        *dpy = XtDisplay (w);
  342.     Window        win = XtWindow (w);
  343.     TPoint        newpupil[2];
  344.     XPoint        xnewpupil, xpupil;
  345.  
  346.     if (XtIsRealized((Widget)w)) {
  347.             XQueryPointer (dpy, win, &rep_root, &rep_child,
  348.              &rep_rootx, &rep_rooty, &dx, &dy, &rep_mask);
  349.         mouse.x = Tx(dx, dy, &w->eyes.t);
  350.         mouse.y = Ty(dx, dy, &w->eyes.t);
  351.         if (!TPointEqual (mouse, w->eyes.mouse)) {
  352.             computePupils (mouse, newpupil);
  353.             xpupil.x = Xx(w->eyes.pupil[0].x, w->eyes.pupil[0].y, &w->eyes.t);
  354.             xpupil.y = Xy(w->eyes.pupil[0].x, w->eyes.pupil[0].y, &w->eyes.t);
  355.             xnewpupil.x =  Xx(newpupil[0].x, newpupil[0].y, &w->eyes.t);
  356.             xnewpupil.y =  Xy(newpupil[0].x, newpupil[0].y, &w->eyes.t);
  357.             if (!XPointEqual (xpupil, xnewpupil)) {
  358.                 if (w->eyes.pupil[0].x != -1000 || w->eyes.pupil[0].y != -1000)
  359.                 eyeBall (w, w->eyes.centerGC, 0);
  360.                 w->eyes.pupil[0] = newpupil[0];
  361.                 eyeBall (w, w->eyes.pupGC, 0);
  362.             }
  363.             xpupil.x = Xx(w->eyes.pupil[1].x, w->eyes.pupil[1].y, &w->eyes.t);
  364.             xpupil.y = Xy(w->eyes.pupil[1].x, w->eyes.pupil[1].y, &w->eyes.t);
  365.             xnewpupil.x =  Xx(newpupil[1].x, newpupil[1].y, &w->eyes.t);
  366.             xnewpupil.y =  Xy(newpupil[1].x, newpupil[1].y, &w->eyes.t);
  367.             if (!XPointEqual (xpupil, xnewpupil)) {
  368.                 if (w->eyes.pupil[1].x != -1 || w->eyes.pupil[1].y != -1)
  369.                 eyeBall (w, w->eyes.centerGC, 1);
  370.                 w->eyes.pupil[1] = newpupil[1];
  371.                 eyeBall (w, w->eyes.pupGC, 1);
  372.             }
  373.             w->eyes.mouse = mouse;
  374.             w->eyes.update = 0;
  375.         } else {
  376.             if (delays[w->eyes.update + 1] != 0)
  377.                 ++w->eyes.update;
  378.         }
  379.     }
  380.     w->eyes.interval_id =
  381.         XtAddTimeOut(delays[w->eyes.update], draw_it, (caddr_t)w);
  382. } /* draw_it */
  383.  
  384. static
  385. repaint_window (w)
  386.     EyesWidget    w;
  387. {
  388.     if (XtIsRealized ((Widget) w)) {
  389.         eyeLiner (w, XtWindow (w), w->eyes.outGC, w->eyes.centerGC, 0);
  390.         eyeLiner (w, XtWindow (w), w->eyes.outGC, w->eyes.centerGC, 1);
  391.         computePupils (w->eyes.mouse, w->eyes.pupil);
  392.         eyeBall (w, w->eyes.pupGC, 0);
  393.         eyeBall (w, w->eyes.pupGC, 1);
  394.     }
  395. }
  396.     
  397. /* ARGSUSED */
  398. static Boolean SetValues (current, request, new)
  399.     Widget current, request, new;
  400. {
  401.     return( FALSE );
  402. }
  403.  
  404. eyeLiner (w, d, outgc, centergc, num)
  405. EyesWidget    w;
  406. Drawable    d;
  407. GC        outgc, centergc;
  408. int        num;
  409. {
  410.     Display *dpy = XtDisplay(w);
  411.  
  412.     TFillArc (dpy, d, outgc, &w->eyes.t,
  413.           EYE_X(num) - EYE_WIDTH / 2.0 - EYE_THICK,
  414.            EYE_Y(num) - EYE_HEIGHT / 2.0 - EYE_THICK,
  415.           EYE_WIDTH + EYE_THICK * 2.0,
  416.            EYE_HEIGHT + EYE_THICK * 2.0,
  417.            90 * 64, 360 * 64);
  418.     if (centergc) {
  419.             TFillArc (dpy, d, centergc, &w->eyes.t,
  420.           EYE_X(num) - EYE_WIDTH / 2.0,
  421.            EYE_Y(num) - EYE_HEIGHT / 2.0,
  422.           EYE_WIDTH, EYE_HEIGHT,
  423.           90 * 64, 360 * 64);
  424.     }
  425. }
  426.  
  427. eyeBall (w, gc, num)
  428. EyesWidget    w;
  429. GC    gc;
  430. int    num;
  431. {
  432.     Display *dpy = XtDisplay(w);
  433.     Window win = XtWindow(w);
  434.  
  435.     TFillArc (dpy, win, gc, &w->eyes.t,
  436.            w->eyes.pupil[num].x - BALL_WIDTH / 2.0,
  437.            w->eyes.pupil[num].y - BALL_HEIGHT / 2.0,
  438.            BALL_WIDTH, BALL_HEIGHT,
  439.           90 * 64, 360 * 64);
  440. }
  441.